#include <fermat/common/directory_iterator.h>
#  pragma GCC diagnostic ignored "-Wshadow"
namespace fermat {


DirectoryIterator::DirectoryIterator(): _pDir(0),_dc(0),_rc(0)
{

}

	
DirectoryIterator::DirectoryIterator(const std::string& path)
	: _path(path)
{
	_rc = init(path);
	if(_rc) {
		return ;
	}
	_path.makeDirectory();
	_path.setFileName(next());
	_file = _path;
}


DirectoryIterator::DirectoryIterator(const DirectoryIterator& iterator)
	:_pDir(iterator._pDir),
	 _rc(iterator._rc), 
	 _path(iterator._path)
	
{
	_dc = iterator._dc;
	if (_pDir && !_rc) 
	{
		_file = _path;
		_current = iterator._current;
	}
}

	
DirectoryIterator::DirectoryIterator(const File& file)
{
	_path = file.path();
	_rc = init(_path.toString());
	if(_rc) {
		return ;
	}
	_path.makeDirectory();
	_path.setFileName(next());
	_file = _path;
}


DirectoryIterator::DirectoryIterator(const Path& path)
{
	_path = path;
	_rc = init(_path.toString());
	if(_rc) {
		return ;
	}
	_path.makeDirectory();
	_path.setFileName(next());
	_file = _path;
}


DirectoryIterator::~DirectoryIterator()
{
	clear();
}


DirectoryIterator& DirectoryIterator::operator = (const DirectoryIterator& it)
{
	if (_pDir) {
		clear();
	}
	_pDir = it._pDir;
	_path = it._path;
	_file = _path;
	_dc = it._dc;
	_current = it._current;
	_rc = it._rc;
	return *this;
}


DirectoryIterator& DirectoryIterator::operator = (const File& file)
{
	if (_pDir) {
		clear();
	}
	_rc = init(file.path());
	if(_rc) {
		return *this;
	}
	_path.parseDirectory(file.path());
	_path.setFileName(next());
	_file = _path;
	return *this;
}


DirectoryIterator& DirectoryIterator::operator = (const Path& path)
{
	if (_pDir) {
		clear();
	}
	_rc = init(path.toString());
	if(_rc) {
		return *this;
	}
	_path = path;
	_path.makeDirectory();
	_path.setFileName(next());
	_file = _path;
	return *this;
}


DirectoryIterator& DirectoryIterator::operator = (const std::string& path)
{
	if (_pDir) {
		clear();
	}
	_rc = init(path);
	if(_rc) {
		return *this;
	}
	_path.parseDirectory(path);
	_path.setFileName(next());
	_file = _path;
	return *this;
}


DirectoryIterator& DirectoryIterator::operator ++ ()
{
	if (_pDir) {
		_path.setFileName(next());
		_file = _path;
	}
	return *this;
}


DirectoryIterator DirectoryIterator::operator ++ (int )
{
	if (_pDir) {
		_path.setFileName(next());
		_file = _path;
	}
	return *this;
}

std::string DirectoryIterator::next()
{
	do {
		struct dirent* pEntry = readdir(_pDir);
		if (pEntry)
			_current = pEntry->d_name;
		else
			_current.clear();
	}
	while (_current == "." || _current == "..");
	return _current;
}
void DirectoryIterator::clear()
{
	if(_pDir) {
		closedir(_pDir);
		_pDir = NULL;
	}
	_current.clear();
	_path = "";
	_file = "";
	_dc = 0;
	_rc = 0;
}
int DirectoryIterator::init(const std::string &path)
{
	int rc = 0;
	Path p(path);
	p.makeFile();
	_pDir = opendir(p.toString().c_str());
	if (!_pDir)  {
		rc = errno;
		_dc = 0;
	}
	_dc = 1;
	return rc;
}
} 
